home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / nihcl-30.lha / nihcl-3.0 / vector / BitVec.m4 < prev    next >
Text File  |  1990-05-16  |  15KB  |  653 lines

  1. /* BitVec.m4 -- M4 code templates for NIHCL BitVec class
  2.  
  3.     THIS SOFTWARE FITS THE DESCRIPTION IN THE U.S. COPYRIGHT ACT OF A
  4.     "UNITED STATES GOVERNMENT WORK".  IT WAS WRITTEN AS A PART OF THE
  5.     AUTHOR'S OFFICIAL DUTIES AS A GOVERNMENT EMPLOYEE.  THIS MEANS IT
  6.     CANNOT BE COPYRIGHTED.  THIS SOFTWARE IS FREELY AVAILABLE TO THE
  7.     PUBLIC FOR USE WITHOUT A COPYRIGHT NOTICE, AND THERE ARE NO
  8.     RESTRICTIONS ON ITS USE, NOW OR SUBSEQUENTLY.
  9.  
  10. Author:
  11.     K. E. Gorlen
  12.     Bg. 12A, Rm. 2033
  13.     Computer Systems Laboratory
  14.     Division of Computer Research and Technology
  15.     National Institutes of Health
  16.     Bethesda, Maryland 20892
  17.     Phone: (301) 496-1111
  18.     uucp: uunet!nih-csl!kgorlen
  19.     Internet: kgorlen@alw.nih.gov
  20.     June, 1986
  21.  
  22. Function:
  23.     
  24. This file contains M4 macro definitions for some of the functions
  25. needed to implement the NIHCL bit vector class.
  26.  
  27. Modification History:
  28.  
  29. $Log:    BitVec.m4,v $
  30. Revision 3.0  90/05/16  23:00:24  kgorlen
  31. Release for 1st edition.
  32.  
  33. */
  34. // WARNING: Modify the M4 macros, not the C++ code they generate!
  35. // WARNING: Assumes 8 bits per character.
  36.  
  37. `#include' "IntVec.h"
  38. `#include' "bitstreams.h"
  39. `#include' "nihclconfig.h"
  40. `#include' "nihclIO.h"
  41.  
  42. `#define'    THIS    BitVec
  43. `#define'    BASE    Vector
  44. `#define'    BASE_CLASSES Vector::desc()
  45. `#define'    MEMBER_CLASSES
  46. `#define'    VIRTUAL_BASE_CLASSES
  47.  
  48. DEFINE_CLASS(BitVec,1,"$Header: /afs/alw.nih.gov/unix/sun4_40c/usr/local/src/nihcl-3.0/share/vector/RCS/BitVec.m4,v 3.0 90/05/16 23:00:24 kgorlen Rel $",NULL,NULL);
  49.  
  50. extern const int NIHCL_INDEXRANGE;
  51. extern const int NIHCL_SLICERANGE;
  52. extern const int NIHCL_VECTORLENGTH;
  53. extern const int NIHCL_VECTORSELECT;
  54.  
  55. inline unsigned nbytes(unsigned n)    { return (n+7) >> 3; }
  56.  
  57. void byteCopy(const bitVecByte* src, bitVecByte* dst, unsigned long count)
  58. // Copy n bytes from src to dst.
  59. {
  60.     const bitVecByte* sp = src;
  61.     bitVecByte* dp = dst;
  62. #ifndef DUFF
  63.     unsigned long n = count;
  64.     while (n--) *dp++ = *sp++;
  65. #else
  66. //  Unrolled loop using Duff's Device:
  67.     unsigned long n = (count+7)>>3;
  68.     switch (count & 7) {
  69.         case 0:    do {    *dp++ = *sp++;
  70.         case 7:        *dp++ = *sp++;
  71.         case 6:        *dp++ = *sp++;
  72.         case 5:        *dp++ = *sp++;
  73.         case 4:        *dp++ = *sp++;
  74.         case 3:        *dp++ = *sp++;
  75.         case 2:        *dp++ = *sp++;
  76.         case 1:        *dp++ = *sp++;
  77.         } while (--n > 0);
  78.     }
  79. #endif
  80. }
  81.  
  82. static union hash_byte_mask {
  83.     unsigned in[sizeof(int)];
  84.     char ch[sizeof(int)*sizeof(int)];
  85.     hash_byte_mask();
  86. } mask;
  87.  
  88. hash_byte_mask::hash_byte_mask()
  89. {
  90.     for (unsigned i=0; i<sizeof(int); i++) {
  91.         for (unsigned j=0; j<sizeof(int); j++) ch[sizeof(int)*i+j] = j<i ? 0xff : 0;
  92.     }
  93. }
  94.  
  95. unsigned THIS::hash() const
  96. {
  97.     unsigned h = nbytes();
  98.     unsigned i = div_sizeof_int(nbytes());
  99.     unsigned* vp = (unsigned*)v;
  100.     while (i--) h ^= *vp++;
  101.     if ((i = mod_sizeof_int(nbytes())) != 0)
  102.         h ^= *vp & mask.in[i];
  103.     return h;
  104. }
  105.  
  106. void THIS::printOn(ostream& strm) const
  107. {
  108.     for (unsigned i=0; i<length(); i++) {
  109.         if (i>0 && (i%25 == 0)) strm << "\n\t";
  110.         strm << ((*this)(i) ? "1 " : "0 ");
  111.     }
  112. }
  113.  
  114. void THIS::scanFrom(istream& strm)
  115. {
  116.     extern const int NIHCL_NYET;
  117.     setError(NIHCL_NYET,DEFAULT,className(),"scanFrom");
  118. }
  119.  
  120. THIS::THIS(OIOin& strm) : BASE(strm)
  121. {
  122.     v = new bitVecByte[nbytes()];
  123.     strm.get(v,nbytes());
  124. }
  125.  
  126. void THIS::storer(OIOout& strm) const
  127. {
  128.     BASE::storer(strm);
  129.     strm.put(v,nbytes());
  130. }
  131.  
  132. THIS::THIS(OIOifd& fd) : BASE(fd)
  133. {
  134.     v = new bitVecByte[nbytes()];
  135.     fd.get(v,nbytes());
  136. }
  137.  
  138. void THIS::storer(OIOofd& fd) const
  139. {
  140.     BASE::storer(fd);
  141.     fd.put(v,nbytes());
  142. }
  143.  
  144. bool BitVec::isEqual(const Object& u) const
  145. // Test for two BitVecs equal.
  146. {
  147.     const BitVec* U = castdown(&u);
  148.     if (!u.isSpecies(classDesc) || n!=U->n) return NO;
  149.     unsigned i = nbytes();
  150.     bitVecByte* vp = v;
  151.     bitVecByte* up = U->v;
  152.     while (i--) if (*vp++ != *up++) return NO;
  153.     return YES;
  154. }
  155.                                     
  156. const Class* BitVec::species() const    { return &classDesc; }
  157.  
  158. void BitVec::deepenShallowCopy() {}
  159.  
  160. void BitVec::indexRangeErr() const
  161. {
  162.     setError(NIHCL_INDEXRANGE,DEFAULT,this,className());
  163. }
  164.  
  165. void BitVec::selectErr(const BitVec& V) const
  166. {
  167.     setError(NIHCL_VECTORSELECT,DEFAULT,this,"BitVec",length(),sum(V),&V,V.length());
  168. }
  169.  
  170. void BitSlice::selectErr(const BitVec& V) const
  171. {
  172.     setError(NIHCL_VECTORSELECT,DEFAULT,this,"BitSlice",length(),sum(V),&V,V.length());
  173. }
  174.  
  175. BitVec::BitVec(unsigned lngth) : BASE(lngth)
  176. // Construct an uninitialized BitVec of the length specified.
  177. {
  178.     v = NULL;
  179.     if (lngth != 0) v = new bitVecByte[nbytes()];
  180. }
  181.  
  182. BitVec::BitVec(unsigned lngth, bool init) : BASE(lngth)
  183. // Construct a BitVec of the length specified and initialize it.
  184. {
  185.     v = NULL;
  186.     if ((lngth) != 0) {
  187.         v = new bitVecByte[nbytes()];
  188.         *this = init;
  189.     }
  190. }
  191.  
  192. BitVec::BitVec(const bitVecByte* src, unsigned lngth) : BASE(lngth)
  193. // Construct a BitVec and initialize it from the specified byte vector.
  194. {
  195.     v = NULL;
  196.     if (lngth != 0) {
  197.         int l = nbytes();
  198.         v = new bitVecByte[l];
  199.         byteCopy(src,v,l);
  200.     }
  201. }
  202.  
  203. BitVec::BitVec(const BitVec& U) : BASE(U.n)
  204. // Construct a BitVec and initialize it from the specified BitVec U.
  205. {
  206.     v = NULL;
  207.     if (n != 0) {
  208.         int l = nbytes();
  209.         v = new bitVecByte[l];
  210.         byteCopy(U.v,v,l);
  211.     }
  212. }
  213.  
  214. BitVec::BitVec(const BitSlice& s) : BASE(0)
  215. // Construct a BitVec from a slice of another BitVec.
  216. {
  217.     v = NULL;
  218.     *this = s;
  219. }
  220.  
  221. BitSlice::BitSlice(const BitVec& v, int pos, unsigned lgt, int stride)
  222. // Construct a BitSlice from a BitVec.
  223. {
  224.     if ((unsigned)(pos + (lgt-1)*stride) >= v.length())
  225.         setError(NIHCL_SLICERANGE,DEFAULT,&v,v.className(),v.length(),pos,lgt,stride);
  226.     V = &(BitVec&)v;  p = pos;  l = lgt;  k = stride;
  227. }
  228.  
  229. BitSlice::BitSlice(const BitSlice& s)
  230. // private BitSlice copy constructor
  231. {
  232.     V = s.V;
  233.     p = s.p;
  234.     l = s.l;
  235.     k = s.k;
  236. }
  237.  
  238. BitSlice::BitSlice(const BitSlct& s)
  239. // Construct a BitVec slice from IntVec-subscripted elements of BitVec
  240. // Can't do this with BitSlct::operator BitSlice() because of TempBitVec
  241. {
  242.     BitVec& T = *new TempBitVec();
  243.     T = (*s.V)[*s.B];
  244.     V = &T;  p = 0;  l = T.length();  k = 1;
  245. }
  246.  
  247. BitSlice::BitSlice(const BitPick& s)
  248. // Construct a BitVec slice from IntVec-subscripted elements of BitVec
  249. // Can't do this with BitPick::operator BitSlice() because of TempBitVec
  250. {
  251.     BitVec& T = *new TempBitVec();
  252.     T = (*s.V)[*s.X];
  253.     V = &T;  p = 0;  l = T.length();  k = 1;
  254. }
  255.  
  256. void BitVec::operator=(const BitVec& U)
  257. // Assign the argument BitVec U to this BitVec.
  258. {
  259.     if (v != U.v) {
  260.         delete v;
  261.         v = NULL;
  262.         if ((n = U.n) != 0) {
  263.             int l = nbytes();
  264.             v = new bitVecByte[l];
  265.             byteCopy(U.pt(),v,l);
  266.         }
  267.     }
  268. }
  269.  
  270. void BitVec::operator=(const BitSlice& s)
  271. // Assign a slice of a BitVec to this BitVec.
  272. {
  273.     if ((n = s.length()) == 0) {        // empty slice
  274.         delete v;
  275.         v = NULL;
  276.         return;
  277.     }
  278.     bitVecByte* t = v;
  279.     if (this != s.V) delete t;    // not V = V(i,j,k)
  280.     bitVecByte* u = new bitVecByte[nbytes()];
  281.     BitSliceIstream src(s);
  282.     BITVECGEN(u, length(), src)
  283.     v = u;
  284.     if (this == s.V) delete t;    // case V = V[BitVec&]
  285. }
  286.  
  287. void BitVec::operator=(const BitSlct& s)
  288. // Assign the BitVec-selected elements of a BitVec to this BitVec.
  289. {
  290.     if ((n = sum(*s.B)) == 0) {    // return zero length result
  291.         delete v;
  292.         v = NULL;
  293.         return;
  294.     }
  295.     BitVecIstream src(*s.V);
  296.     BitVecIstream slct(*s.B);
  297.     bitVecByte* t = v;
  298.     if (this != s.V) delete t;    // not V = V[BitVec&]
  299.     v = new bitVecByte[nbytes()];
  300.     BitVecOstream dst(*this);
  301.     unsigned i = s.length();
  302.     while(i--) {
  303.         if (slct) dst << src;
  304.         slct++;
  305.         src++;
  306.     }
  307.     if (this == s.V) delete t;    // case V = V[BitVec&]
  308. }
  309.  
  310. void BitVec::operator=(const BitPick& s)
  311. // Assign the IntVec-subscripted elements of a BitVec to this BitVec.
  312. {
  313.     unsigned l = s.length();
  314.     if (l == 0) {        // empty IntVec
  315.         delete v;
  316.         n = 0;  v = NULL;
  317.         return;
  318.     }
  319.     bitVecByte* t = v;
  320.     if (this != s.V) delete t;    // not V = V[IntVec]
  321.     bitVecByte* u = new bitVecByte[::nbytes(l)];
  322.     BitPickIstream src(s);
  323.     BITVECGEN(u, l, src)
  324.     n = l;  v = u;
  325.     if (this == s.V) delete t;    // case V = V[IntVec&]
  326. }
  327.  
  328. void BitVec::operator=(bool scalar)
  329. // Assign a scalar Boolean to all elements of this BitVec.
  330. {
  331.     int i = nbytes();
  332.     bitVecByte* dp = v;
  333.     if (i>0) {
  334.         if (scalar) {
  335.             while (--i) *dp++ = 0xff;
  336.             *dp = charBitMask(n&7)-1;
  337.         }
  338.         else while (i--) *dp++ = 0;
  339.     }
  340. }
  341.  
  342. BitVec operator!(const BitVec& U)
  343. // Unary bitwise operator on a BitVec.
  344. {
  345.     int i = U.nbytes();
  346.     BitVec T(U.length());
  347.     bitVecByte* dp = T.pt();
  348.     const bitVecByte* up = U.pt();
  349.     while (i--) *dp++ = ~(*up++);
  350.     if ((i = U.length()&7) != 0) {
  351.         --dp;
  352.         *dp &= NIHCL::charBitMask(i)-1;
  353.     }
  354.     return T;
  355. }
  356.  
  357. void BitSlice::operator=(const BitVec& U)
  358. // Assign a BitVec to this BitVec slice.
  359. {
  360.     if (length() != U.length()) lengthErr(U);
  361.     BitSliceOstream dst(*this);
  362.     bitVecByte m;
  363.     const bitVecByte* bp = U.pt();
  364.     unsigned i = length() >> 3;
  365.     while (i--) {
  366.         m = *bp++;
  367.         dst << (m&1);  m >>= 1;
  368.         dst << (m&1);  m >>= 1;
  369.         dst << (m&1);  m >>= 1;
  370.         dst << (m&1);  m >>= 1;
  371.         dst << (m&1);  m >>= 1;
  372.         dst << (m&1);  m >>= 1;
  373.         dst << (m&1);  m >>= 1;
  374.         dst << (m&1);
  375.     }
  376.     i = length() & 7;
  377.     m = *bp;
  378.     while (i--) {
  379.         dst << (m&1);  m >>= 1;
  380.     }
  381. }
  382.  
  383. void BitSlice::operator=(const BitSlice& s)
  384. // Assign a BitVec slice to this BitVec slice.
  385. {
  386.     unsigned i = length();
  387.     if (i != s.length()) lengthErr(s);
  388.     BitSliceIstream src(s);
  389.     BitSliceOstream dst(*this);
  390.     while (i--) dst << src;
  391. }
  392.  
  393. void BitSlice::operator=(const BitPick& s)
  394. // Assign the IntVec-subscripted elements of a BitVec to this BitVec slice.
  395. {
  396.     int i = length();
  397.     if (i != s.length()) lengthErr(*s.X);
  398.     BitSliceOstream dst(*this);
  399.     BitPickIstream src(s);
  400.     while (i--) dst << src;
  401. }
  402.  
  403. void BitSlice::operator=(const BitSlct& s)
  404. // Assign the BitVec-selected elements of a BitVec to this BitVec slice.
  405. {
  406.     if (l != sum(*s.B)) selectErr(*s.B);
  407.     BitVecIstream src(*s.V);
  408.     BitVecIstream slct(*s.B);
  409.     BitSliceOstream dst(*this);
  410.     unsigned i = s.length();
  411.     while(i--) {
  412.         if (slct) { dst << src; }
  413.         slct++;
  414.         src++;
  415.     }
  416. }
  417.  
  418. void BitSlice::operator=(bool scalar)
  419. // Assign a scalar to all elements of this BitVec slice.
  420. {
  421.     int i = length();
  422.     int j = stride();
  423.     int x = pos();
  424.     BitVec& D = *V;
  425.     bool c = scalar;
  426.     while (i--) { D(x) = c; x += j; }
  427. }
  428.  
  429. BitVec operator!(const BitSlice& s)
  430. // Unary operator on BitVec slice.
  431. {
  432.     BitVec T(s.length());
  433.     BitSliceIstream src(s);
  434.     BITVECGEN(T.pt(), s.length(), !src)
  435.     return T;
  436. }
  437.  
  438. void BitPick::operator=(const BitVec& U)
  439. // Assign a BitVec to the IntVec-subscripted elements of this BitVec.
  440. {
  441.     if (length() != U.length()) lengthErr(*X,U);
  442.     BitPickOstream dst(*this);
  443.     bitVecByte m;
  444.     const bitVecByte* bp = U.pt();
  445.     unsigned i = length() >> 3;
  446.     while (i--) {
  447.         m = *bp++;
  448.         dst << (m&1);  m >>= 1;
  449.         dst << (m&1);  m >>= 1;
  450.         dst << (m&1);  m >>= 1;
  451.         dst << (m&1);  m >>= 1;
  452.         dst << (m&1);  m >>= 1;
  453.         dst << (m&1);  m >>= 1;
  454.         dst << (m&1);  m >>= 1;
  455.         dst << (m&1);  m >>= 1;
  456.     }
  457.     i = length() & 7;
  458.     m = *bp;
  459.     while (i--) {
  460.         dst << (m&1);  m >>= 1;
  461.     }
  462. }
  463.  
  464. void BitPick::operator=(const BitPick& s)
  465. // Assign the IntVec-subscripted elements of a BitVec to the IntVec-subscripted elements of this BitVec.
  466. {
  467.     int i = length();
  468.     if (i != s.length()) lengthErr(*X,*s.X);
  469.     BitPickIstream src(s);
  470.     BitPickOstream dst(*this);
  471.     while (i--) dst << src;
  472. }
  473.  
  474. void BitPick::operator=(const BitSlct& s)
  475. // Assign the BitVec-selected elements of a BitVec to the IntVec-subscripted elements of this BitVec.
  476. {
  477.     if (length() != sum(*s.B)) X->selectErr(*s.B);
  478.     BitVecIstream src(*s.V);
  479.     BitVecIstream slct(*s.B);
  480.     BitPickOstream dst(*this);
  481.     unsigned i = s.length();
  482.     while(i--) {
  483.         if (slct) { dst << src; }
  484.         slct++;
  485.         src++;
  486.     }
  487. }
  488.  
  489. void BitPick::operator=(const BitSlice& s)
  490. // Assign a BitVec slice to the IntVec-subscripted elements of this BitVec.
  491. {
  492.     int i = length();
  493.     if (i != s.length()) s.lengthErr(*X);
  494.     BitSliceIstream src(s);
  495.     BitPickOstream dst(*this);
  496.     while (i--) dst << src;
  497. }
  498.  
  499. void BitPick::operator=(bool scalar)
  500. // Assign a scalar to the IntVec-subscripted elements of this BitVec.
  501. {
  502.     int i = length();
  503.     bool c = scalar;
  504.     BitPickOstream dst(*this);
  505.     while (i--) { dst << c; }
  506. }
  507.  
  508. void BitSlct::operator=(const BitVec& U)
  509. // Assign a BitVec to the BitVec-selected elements of this BitVec.
  510. {
  511.     if (U.length() != sum(*B)) U.selectErr(*B);
  512.     BitVecIstream src(U);
  513.     BitVecOstream dst(*V);
  514.     BITVECSCAN(*B, length(), { dst << src;  src++; }  else dst++)
  515. }
  516.  
  517. void BitSlct::operator=(const BitPick& s)
  518. // Assign the IntVec-subscripted elements of a BitVec to the BitVec-selected elements of this BitVec.
  519. {
  520.     if (s.length() != sum(*B)) s.X->selectErr(*B);
  521.     BitPickIstream src(s);
  522.     BitVecOstream dst(*V);
  523.     BITVECSCAN(*B, length(), dst << src;  else dst++)
  524. }
  525.  
  526. void BitSlct::operator=(const BitSlct& s)
  527. // Assign the BitVec-selected elements of a BitVec to the BitVec-selected elements of this BitVec.
  528. {
  529.     BitVec T;
  530.     T = (*s.V)[*s.B];
  531.     (*V)[*B] = T;
  532. }
  533.  
  534. void BitSlct::operator=(const BitSlice& s)
  535. // Assign a BitVec slice to the BitVec-selected elements of this BitVec.
  536. {
  537.     if (s.length() != sum(*B)) s.selectErr(*B);
  538.     BitSliceIstream src(s);
  539.     BitVecOstream dst(*V);
  540.     BITVECSCAN(*B, length(), dst << src;  else dst++)
  541. }
  542.  
  543. void BitSlct::operator=(bool scalar)
  544. // Assign a scalar to the BitVec-selected elements of this BitVec.
  545. {
  546.     BitVecOstream dst(*V);
  547.     BITVECSCAN(*B, length(), dst << scalar;  else dst++)
  548. }
  549.  
  550. BitVec reverse(const BitSlice& s)
  551. // Reverse bit order of BitSlice.
  552. {
  553.     int i = s.length();
  554.     BitVec T(i);
  555.     int k = s.pos();
  556.     int j = s.stride();
  557.     BitVec& S = *s.V;
  558.     while (i--) { T(i) = S[k];  k += j; }
  559.     return T;
  560. }
  561.  
  562. int sum(const BitVec& U)
  563. // Count of ones in the specified BitVec.
  564. {
  565.     int i = U.nbytes();
  566.     const bitVecByte* sp = U.pt();
  567.     int t = 0;
  568.     while (i--) t += NIHCL::bitCount(*sp++);
  569.     return t;
  570. }
  571.  
  572. int sum(const BitSlice& s)
  573. // Count of ones in the specified BitSlice.
  574. {
  575.     int i = s.length();
  576.     int t = 0;
  577.     int k = s.pos();
  578.     int j = s.stride();
  579.     BitVec& S = *s.V;
  580.     while (i--) { if (S[k]) t++;  k += j; }
  581.     return t;
  582. }
  583.  
  584. define(CONCAT,$1$2$3$4$5$6$7$8$9)
  585.  
  586. define(CAP,`CONCAT(translit(substr($1,0,1),abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ),substr($1,1))')
  587.  
  588. define(TYPE1_lengthErr_TYPE2,
  589. void $1::lengthErr(const $2& V) const
  590. {
  591.     setError(NIHCL_VECTORLENGTH,DEFAULT,this,"$1",length(),&V,"$2",V.length());
  592. }
  593. )
  594.  
  595. define(FRIEND_BitVec_OP_BitVec__BitVec,
  596. BitVec operator$2(const BitVec& U, const BitVec& V)
  597. // Binary bitwise operator on two BitVecs.
  598. {
  599.     if (U.length() != V.length()) lengthErr(U,V);
  600.     int i = U.nbytes();
  601.     BitVec T(U.length());
  602.     bitVecByte* dp = T.pt();
  603.     const bitVecByte* up = U.pt();
  604.     const bitVecByte* vp = V.pt();
  605.     while (i--) *dp++ = *up++ $2 *vp++;
  606.     return T;
  607. }
  608. )
  609.  
  610. define(FRIEND_BitVec_ASNOP_BitVec,
  611. void operator$2(BitVec& U, const BitVec& V)
  612. // Binary bitwise assignment operator on two BitVecs.
  613. {
  614.     if (U.length() != V.length()) lengthErr(U,V);
  615.     int i = U.nbytes();
  616.     bitVecByte* up = U.pt();
  617.     const bitVecByte* vp = V.pt();
  618.     while (i--) *up++ $2 *vp++;
  619. }
  620. )
  621.  
  622. define(FRIEND_BitSlice_OP_BitSlice__BitVec,
  623. BitVec operator$2(const BitSlice& u, const BitSlice& v)
  624. // Binary arithmetic operator on two BitVec slices
  625. {
  626.     if (u.length() != v.length()) u.lengthErr(v);
  627.     BitVec T(u.length());
  628.     BitSliceIstream usrc(u);
  629.     BitSliceIstream vsrc(v);
  630.     BITVECGEN(T.pt(), u.length(), (bool)usrc $2 (bool)vsrc)
  631.     return T;
  632. }
  633. )
  634.  
  635. define(FRIEND_BitSlice_ASNOP_BitSlice,
  636. void operator$2(BitSlice& u, const BitSlice& v)
  637. // Assignment arithmetic operator on two BitVec slices.
  638. {
  639.     unsigned i;
  640.     if ((i=u.length()) != v.length()) u.lengthErr(v);
  641.     BitVec& U = *u.V;
  642.     BitVec& V = *v.V;
  643.     int uj = u.pos();
  644.     int vj = v.pos();
  645.     int uk = u.stride();
  646.     int vk = v.stride();
  647.     while (i--) {
  648.         U[uj] $2 V[vj];
  649.         uj += uk;  vj += vk;
  650.     }
  651. }
  652. )
  653.